package com.ray.life;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

public class MapViewActivity extends MapActivity {
    private final String TAG = "MapViewActivity";

    private final static int MENU_SET_SATELLITE = 1;
    private final static int MENU_SET_MAP = 2;

    private final int TIME_TO_UPDATE_DATA_MILLI_SECOND = 24 * 60 * 60 * 1000;
    private final int DISTANCE_TO_UPDATE_DATA = 10 * 1000;
    private final int DISTANCE_TO_RECENTER = 1 * 1000;

    private final int DEFAULT_ZOOM_LEVEL = 12;
    private final int DETAIL_ZOOM_LEVEL = 15;

    /** 9 is Kaohsiung */
    private int mCityIndex = 9;
    private MapController mMapController;
    private LocationManager mLocationManager;
    private LocationProvider mLocationProvider;
    private MapView mMapView;
    private Overlay mNewsOverlay;
    private Drawable mMarker;
    private ArrayList<NewsOverlayItem> mNewsList;

    public static void show(Activity context, int cityIndex) {
        Intent intent = new Intent(context, MapViewActivity.class);
        Bundle bundle = new Bundle();
        bundle.putInt(Constants.KEY_INDEX, cityIndex);
        intent.putExtras(bundle);
        context.startActivity(intent);
    }

    public static void show(Activity context, String address, int newsIndex) {
        Intent intent = new Intent(context, MapViewActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString(Constants.KEY_ADDRESS, address);
        bundle.putInt(Constants.KEY_INDEX, newsIndex);
        intent.putExtras(bundle);
        context.startActivity(intent);
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(final Message msg) {
            setProgressBarIndeterminateVisibility(false);

            if (mMapView.getOverlays().contains(mNewsOverlay)) {
                mMapView.getOverlays().remove(mNewsOverlay);
            }

            mNewsOverlay = new NewsItemizedOverlay(mNewsList, mMarker, MapViewActivity.this);
            mMapView.getOverlays().add(mNewsOverlay);

            mMapView.invalidate();
        }
    };

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        setContentView(R.layout.map_view);

        Bundle bundle = this.getIntent().getExtras();
        mCityIndex = bundle.getInt(Constants.KEY_INDEX);

        mMapView = (MapView) findViewById(R.id.map_view);
        mMapView.setBuiltInZoomControls(true);

        mMarker = getResources().getDrawable(R.drawable.marker);
        mMarker.setBounds(0, 0, mMarker.getIntrinsicWidth(), mMarker.getIntrinsicHeight());

        mNewsList = new ArrayList<NewsOverlayItem>();
    }

    @Override
    public void onStart() {
        super.onStart();
        mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        // mLocationProvider = mLocationManager.getBestProvider(mCriteria, true);
        // mLocationProvider = mLocationManager.getProviders(true).get(0);
        mLocationProvider = mLocationManager.getProvider(LocationManager.GPS_PROVIDER);

        if (mLocationProvider != null) {
            mLocationManager.requestLocationUpdates(mLocationProvider.getName(), TIME_TO_UPDATE_DATA_MILLI_SECOND, DISTANCE_TO_UPDATE_DATA,
                this.locationListenerGetNewsData);
            mLocationManager.requestLocationUpdates(mLocationProvider.getName(), TIME_TO_UPDATE_DATA_MILLI_SECOND, DISTANCE_TO_RECENTER,
                this.locationListenerRecenterMap);
        } else {
            Log.e(TAG, "no location provider available");
            Toast.makeText(this, "The GPS location provider is not available at this time.", Toast.LENGTH_SHORT).show();
            finish();
        }

        mMapController = mMapView.getController();

        Bundle bundle = MapViewActivity.this.getIntent().getExtras();
        if (bundle.containsKey(Constants.KEY_ADDRESS)) { // single entry
            mMapController.setZoom(DETAIL_ZOOM_LEVEL);
            GeoPoint gp = LocationHelper.getGeoPointByAddress(MapViewActivity.this, bundle.getString(Constants.KEY_ADDRESS));
            if (gp != null) {
                mMapController.setCenter(gp);
            } else {
                finish();
            }
        } else { // all entry
            mMapController.setZoom(DEFAULT_ZOOM_LEVEL);
            mMapController.setCenter(Constants.COUNTY_GEOS[mCityIndex]);
        }

        getNewsData();
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(0, MapViewActivity.MENU_SET_MAP, 0, "Map").setIcon(android.R.drawable.ic_menu_mapmode);
        menu.add(0, MapViewActivity.MENU_SET_SATELLITE, 0, "Satellite").setIcon(android.R.drawable.ic_menu_mapmode);

        return true;
    }

    @Override
    public boolean onMenuItemSelected(final int featureId, final MenuItem item) {
        switch (item.getItemId()) {
            case MapViewActivity.MENU_SET_MAP:
                this.mMapView.setSatellite(false);
                break;
            case MapViewActivity.MENU_SET_SATELLITE:
                this.mMapView.setSatellite(true);
                break;
        }

        return super.onMenuItemSelected(featureId, item);
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    private void getNewsData() {
        setProgressBarIndeterminateVisibility(true);

        new Thread() {

            @Override
            public void run() {
                Bundle bundle = MapViewActivity.this.getIntent().getExtras();
                if (bundle.containsKey(Constants.KEY_ADDRESS)) {
                    /** show one discount */
                    mNewsList = getNewsOverlayItems(bundle.getString(Constants.KEY_ADDRESS), bundle.getInt(Constants.KEY_INDEX));
                } else {
                    /** show all discounts */
                    ArrayList<News> newsList = MainActivity.getNewsList();
                    mNewsList = getNewsOverlayItems(newsList);
                }

                // send message to Handler to update UI
                mHandler.sendEmptyMessage(1);
            };
        }.start();
    }

    /** parse data and put them into an ArrayList */
    private ArrayList<NewsOverlayItem> getNewsOverlayItems(ArrayList<News> newsList) {
        ArrayList<NewsOverlayItem> newsOverylayItemList = new ArrayList<NewsOverlayItem>();
        for (News news : newsList) {
            if (!TextUtils.isEmpty(news.getDesc())) {
                String desc = news.getDesc();
                ContentParser cp = new ContentParser(desc);
                cp.parse();

                news.setInfo(cp.getActInfo());
                news.setDuration(cp.getActDuration());
                String address = cp.getActAddr();
                news.setAddress(address);
                Log.e(TAG, "address : " + address);

                cp = null;

                if (!TextUtils.isEmpty(address)) {
                    GeoPoint gp = LocationHelper.getGeoPointByAddress(MapViewActivity.this, address);
                    if (gp != null) {
                        NewsOverlayItem noi = new NewsOverlayItem(gp, news);
                        newsOverylayItemList.add(noi);
                    }
                } else {
                    Log.w(TAG, "address is empty...");
                }
            } else {
                Log.w(TAG, "desc is empty, can not retrieve address");
            }
        }
        return newsOverylayItemList;
    }

    private ArrayList<NewsOverlayItem> getNewsOverlayItems(String address, int newsIndex) {
        ArrayList<NewsOverlayItem> newsOverylayItemList = new ArrayList<NewsOverlayItem>();
        if (!TextUtils.isEmpty(address)) {
            GeoPoint gp = LocationHelper.getGeoPointByAddress(MapViewActivity.this, address);
            if (gp != null) {
                NewsOverlayItem noi = new NewsOverlayItem(gp, MainActivity.getNewsList().get(newsIndex));
                newsOverylayItemList.add(noi);
            }
        } else {
            Log.w(TAG, "address is empty...");
        }
        return newsOverylayItemList;
    }

    private final LocationListener locationListenerGetNewsData = new LocationListener() {

        public void onLocationChanged(final Location loc) {
//            int lat = (int) (loc.getLatitude() * LocationHelper.MILLION);
//            int lon = (int) (loc.getLongitude() * LocationHelper.MILLION);
            // update data
//            GeoPoint geoPoint = new GeoPoint(lat, lon);
            getNewsData();
        }

        public void onProviderDisabled(final String s) {
            // do nothing
        }

        public void onProviderEnabled(final String s) {
            // do nothing
        }

        public void onStatusChanged(final String s, final int i, final Bundle b) {
            // do nothing
        }
    };

    private final LocationListener locationListenerRecenterMap = new LocationListener() {

        public void onLocationChanged(final Location loc) {
            int lat = (int) (loc.getLatitude() * LocationHelper.MILLION);
            int lon = (int) (loc.getLongitude() * LocationHelper.MILLION);
            // animate to new location
            GeoPoint geoPoint = new GeoPoint(lat, lon);
            mMapController.animateTo(geoPoint);
        }

        public void onProviderDisabled(final String s) {
            // do nothing
        }

        public void onProviderEnabled(final String s) {
            // do nothing
        }

        public void onStatusChanged(final String s, final int i, final Bundle b) {
            // do nothing
        }
    };
}
